package com.restaurant.application.util.wx.wxpay;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.restaurant.application.util.wx.WxConfig;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

public class WeXinPay {
    private static final ObjectMapper mapper = new ObjectMapper();

    public static Map createOrder(String orderId, BigDecimal price, String body, String ipAddress) throws IOException {
        SortedMap<String, Object> parameters = new TreeMap<>();
        parameters.put("appid", WxConfig.APPID);
        parameters.put("mch_id", WxConfig.MCH_ID);
        parameters.put("device_info", "WEB"); // 默认 "WEB"
        parameters.put("body", body);
        parameters.put("nonce_str", WxUtils.gen32RandomString()); // 32 位随机字符串
        parameters.put("notify_url", WxConfig.NOTIFY_URL);
        parameters.put("out_trade_no", orderId);
        parameters.put("total_fee", price.multiply(BigDecimal.valueOf(100)).intValue());
//        parameters.put("total_fee", 1); // 测试时，将支付金额设置为 1 分钱
        parameters.put("spbill_create_ip", ipAddress);
        parameters.put("trade_type", "APP");
        parameters.put("sign", WxUtils.createSign(parameters, WxConfig.KEY)); // sign 必须在最后
        String result = WxUtils.executeHttpPost(WxConfig.APP_PAY_URL, parameters); // 执行 HTTP 请求，获取接收的字符串（一段 XML）
        return WxUtils.createSign2(result, WxConfig.KEY);
    }

    public static Map createOrderByMiniApp(String orderId, BigDecimal price, String body, String ipAddress, String openId) throws IOException {
        SortedMap<String, Object> parameters = new TreeMap<>();
        parameters.put("appid", WxConfig.APPID2);
        parameters.put("mch_id", WxConfig.MCH_ID);
//        parameters.put("device_info", "WEB"); // 默认 "WEB"
        parameters.put("body", body);
        parameters.put("nonce_str", WxUtils.gen32RandomString()); // 32 位随机字符串
        parameters.put("notify_url", WxConfig.NOTIFY_URL);
        parameters.put("out_trade_no", orderId);
        parameters.put("total_fee", price.multiply(BigDecimal.valueOf(100)).intValue());
//        parameters.put("total_fee", 1); // 测试时，将支付金额设置为 1 分钱
        parameters.put("spbill_create_ip", ipAddress);
        parameters.put("trade_type", "JSAPI");
        parameters.put("openid", openId);
        parameters.put("sign", WxUtils.createSign(parameters, WxConfig.KEY)); // sign 必须在最后
        String result = WxUtils.executeHttpPost(WxConfig.APP_PAY_URL, parameters); // 执行 HTTP 请求，获取接收的字符串（一段 XML）
        return WxUtils.createSign2ByMiniApp(result, WxConfig.KEY);
    }

    /**
     * 查询订单
     *
     * @param orderId 商户自己的订单号
     * @return
     */
    public static Map getOrder(String orderId) throws IOException {
        SortedMap<String, Object> reqMap = new TreeMap<>();
        reqMap.put("appid", WxConfig.APPID);
        reqMap.put("mch_id", WxConfig.MCH_ID);
        reqMap.put("nonce_str", WxUtils.gen32RandomString());
        reqMap.put("out_trade_no", orderId); //商户系统内部的订单号,
        reqMap.put("sign", WxUtils.createSign(reqMap, WxConfig.KEY)); // sign 必须在最后

        String retStr = WxUtils.executeHttpPost(WxConfig.OrderUrl, reqMap);
        return WxUtils.transferXmlToMap(retStr);
    }

    public static WechatPayRet callBack(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 预先设定返回的 response 类型为 xml
        response.setHeader("Content-type", "com/tunbao/application/xml");
        // 读取参数，解析Xml为map
        Map<String, String> map = WxUtils.transferXmlToMap(WxUtils.readRequest(request));
        // 转换为有序 map，判断签名是否正确
        boolean isSignSuccess = WxUtils.checkSign(new TreeMap<>(map), WxConfig.KEY);
        if (isSignSuccess) {
            // 签名校验成功，说明是微信服务器发出的数据
            String orderId = map.get("out_trade_no");
            //if (tradeService.hasProcessed(orderId)) // 判断该订单是否已经被接收处理过
            //return success();
            // 可在此持久化微信传回的该 map 数据
            //..
            if ("SUCCESS".equals(map.get("return_code"))) {
                if ("SUCCESS".equals(map.get("result_code"))) {
                    //orderService.finishOrder(orderId);  // 支付成功
                } else {
                    //orderService.failOrder(orderId);    // 支付失败
                }
            }

            return mapper.convertValue(map, WechatPayRet.class);
        } else {
            // 签名校验失败（可能不是微信服务器发出的数据）
            return null;
        }
    }

    public static String fail() {
        return "<xml>\n" +
                "  <return_code><![CDATA[FAIL]]></return_code>\n" +
                "  <return_msg><![CDATA[]]></return_msg>\n" +
                "</xml>";
    }

    public static String success() {
        return "<xml>\n" +
                "  <return_code><![CDATA[SUCCESS]]></return_code>\n" +
                "  <return_msg><![CDATA[OK]]></return_msg>\n" +
                "</xml>";
    }
}
